﻿using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.DataSourcesRaster;
using System.IO;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.GeoDatabaseExtensions;
using ESRI.ArcGIS.Display;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.GISClient;

namespace PlanningGIS.ArcGIS
{
    /// <summary>
    /// 图层操作类
    /// </summary>
    [ComVisible(true)]
    public class LayerHelper
    {
        /// <summary>
        /// dwg文件类型格式
        /// </summary>
        private static readonly string _ExtensionCad = "*.dwg;*.dxf;*.dgn";

        /// <summary>
        /// 栅格数据文件格式
        /// </summary>
        private static readonly string _ExtensionRaster = "*.jpg;*.jpeg;*.bmp;*.png;*.img;*.sid;*.tif;*.tiff";

        /// <summary>
        /// 雷达数据文件格式
        /// </summary>
        private static readonly string _ExtensionLas = "*.las";

        /// <summary>
        /// 获取文件图层，支持 cad文件（*.dwg;*.dxf;*.dgn）;
        /// 栅格文件（*.jpg;*.jpeg;*.bmp;*.png;*.img;*.sid;*.tif;*.tiff）;
        /// 激光雷达（*.las）等
        /// </summary>
        /// <param name="fullname">文件全路径名称</param>
        /// <param name="spatialReference">空间参考，打开激光雷达数据时用</param>
        /// <returns></returns>
        public static ILayer GetFileLayer(string fullname, ISpatialReference spatialReference = null)
        {
            try
            {
                if (fullname.ToLower().Contains(".gdb") || fullname.ToLower().Contains(".mdb") || fullname.ToLower().Contains(".shp"))
                {
                    IFeatureClass featcls = GeodatabaseHelper.OpenFeatureClass(fullname);
                    if (featcls == null) return null;
                    return featcls.GetFeatureLayer();
                }
                else
                {
                    string extension = System.IO.Path.GetExtension(fullname).ToLower();
                    if (!string.IsNullOrWhiteSpace(extension))
                    {
                        if (_ExtensionCad.Contains(extension))
                        {
                            return CadHelper.GetGroupLayer(fullname);
                        }
                        else if (_ExtensionRaster.Contains(extension))
                        {
                            return LayerHelper.GetRasterLayer(fullname);
                        }
                        else if (_ExtensionLas.Contains(extension))
                        {
                            return GetLasLayer(fullname, spatialReference);
                        }
                        return null;
                    }
                    else
                    {
                        string fpath = System.IO.Path.GetDirectoryName(fullname);
                        string fname = System.IO.Path.GetFileNameWithoutExtension(fullname);
                        return GetRasterLayer(fpath, fname);
                    }
                }
            }
            catch
            {
                return null;
            }
        }

        /// <summary>     ++++++
        /// 获取栅格文件图层
        /// </summary>
        /// <param name="fullname">栅格文件全路径名称（*.jpg;*.jpeg;*.bmp;*.png;*.img;*.sid;*.tif;*.tiff）</param>
        /// <returns></returns>
        public static ILayer GetRasterLayer(string fullname)
        {
            string fpath = System.IO.Path.GetDirectoryName(fullname);
            string fname = System.IO.Path.GetFileName(fullname);
            return GetRasterLayer(fpath, fname);
        }

        /// <summary>
        /// 获取栅格数据图层，切片服务也可当作栅格数据，此时name为Layers
        /// </summary>
        /// <param name="path">目录地址</param>
        /// <param name="name">名称</param>
        /// <returns></returns>
        public static IRasterLayer GetRasterLayer(string path, string name)
        {
            IRasterWorkspace2 rwk = new RasterWorkspaceFactory().OpenFromFile(path, 0) as IRasterWorkspace2;
            IRasterDataset rds = rwk.OpenRasterDataset(name); 
            IRasterLayer lyr = new RasterLayer();
            lyr.CreateFromDataset(rds);
            return lyr;

        }

        /// <summary>
        /// 获取las激光雷达数据ILasDatasetLayer
        /// </summary>
        /// <param name="fullname">文件全路径名称</param>
        /// <param name="spatialReference">空间参考</param>
        /// <returns></returns>
        public static ILayer GetLasLayer(string fullname, ISpatialReference spatialReference = null)
        {
            string lasd = fullname.Substring(0, fullname.Length - 4) + ".lasd";
            if (!File.Exists(lasd))
            {
                string message = "";
                if (!WorkspaceHelper.CreateLasWorkspace(fullname, spatialReference, out message))
                    throw new Exception(message);
            }
            ILasDatasetWorkspace wksp = (ILasDatasetWorkspace)WorkspaceHelper.OpenLasWorkspace(lasd);
            ILasDataset pLasDs = wksp.OpenLasDataset(System.IO.Path.GetFileName(lasd));
            ILasDatasetLayer pLasDsLyr = new LasDatasetLayer() as ILasDatasetLayer;
            pLasDsLyr.Dataset = pLasDs;
            pLasDsLyr.Name = System.IO.Path.GetFileNameWithoutExtension(lasd);
            return pLasDsLyr;
        }

        /// <summary>
        /// 获取WMTS服务图层
        /// </summary>
        /// <param name="url">WMTS服务地址</param>
        /// <returns></returns>
        public static IWMTSLayer GetWMTSLayer(string url)
        {
            IPropertySet pPropertyset = new PropertySet();
            pPropertyset.SetProperty("url", url);
            IWMTSConnectionFactory pwmtsconnectionfactory = new WMTSConnectionFactory();
            IWMTSConnection con = pwmtsconnectionfactory.Open(pPropertyset, 0, null);
            IWMTSLayer ly = new WMTSLayer();
            IName n = con.FullName;
            ly.Connect(n);
            return ly;
        }

        /// <summary>
        /// 获取地图REST服务
        /// </summary>
        /// <param name="location">服务地址 http://myServer:6080/arcgis/rest/services/WaterMap2015/MapServer </param>
        /// <returns></returns>
        public static IMapServerRESTLayer GetRESTLayer(string location)
        {
            IMapServerRESTLayer pRestLayer = new MapServerRESTLayer();
            pRestLayer.Connect(location);
            return pRestLayer;
        }

        /// <summary>
        /// 保存为图层文件
        /// </summary>
        /// <param name="layer"></param>
        /// <param name="name"></param>
        public static void SaveLayerFile(ILayer layer, string name)
        {
            ILayerFile layerFile = new LayerFileClass(); //创建图层文件实例            
            layerFile.New(name); //创建图层文件
            layerFile.ReplaceContents(layer); //和实际图层相关联
            layerFile.Save(); //保存图层文件
        }

        /// <summary>
        /// 获取文件图层的类型
        /// </summary>
        /// <param name="fullname">文件全路径名称</param>
        /// <returns></returns>
        public static zjgisFeatureType GetFileLayerType(string fullname)
        {
            string extension = System.IO.Path.GetExtension(fullname).ToLower();
            if (_ExtensionCad.Contains(extension))
            {
                return zjgisFeatureType.Cad;
            }
            else if (_ExtensionRaster.Contains(extension))
            {
                return zjgisFeatureType.Raster;
            }
            else if (_ExtensionLas.Contains(extension))
            {
                return zjgisFeatureType.LasDataset;
            }
            return zjgisFeatureType.Null;
        }

        /// <summary>
        /// 获取数据集合列表中所有的要素类
        /// </summary>
        /// <param name="datasets">Dataset列表</param>
        /// <param name="sort">是否根据点线面进行排序</param>
        /// <returns>图层列表</returns>
        public static List<ILayer> GetLayersOfDataset(List<IDataset> datasets, bool sort = true)
        {
            List<ILayer> lst = new List<ILayer>();
            foreach (IDataset ds in datasets)
            {
                switch (ds.Type)//根据当前所有的图层的数据集类型加载相应的图层
                {
                    case esriDatasetType.esriDTFeatureDataset:
                        List<IFeatureLayer> tplst = GetLayersOfDataset(ds as IFeatureDataset, false);
                        if (tplst != null && tplst.Count > 0)
                            lst.AddRange(tplst);
                        break;
                    default:
                        ILayer lyr = ds.GetLayer();
                        if (lyr != null) lst.Add(lyr);
                        break;
                }
            }
            if (sort) lst.Sort2();
            return lst;
        }

        /// <summary>
        /// 获取数据集中所有的要素类
        /// </summary>
        /// <param name="dataset">数据集对象</param>
        /// <param name="sort">是否根据点线面进行排序</param>
        /// <returns></returns>
        public static List<IFeatureLayer> GetLayersOfDataset(IFeatureDataset dataset, bool sort = true)
        {
            if (dataset == null) return null;
            List<IFeatureLayer> lst = new List<IFeatureLayer>();
            IEnumDataset dses = dataset.Subsets;
            IDataset ds = null;
            while ((ds = dses.Next()) != null)
            {
                IFeatureLayer flyr = (ds as IFeatureClass).GetFeatureLayer();
                lst.Add(flyr);
            }
            if (sort) lst.Sort2();
            return lst;
        }

        /// <summary>
        /// 设置图层的显示状态
        /// </summary>
        /// <param name="map">地图对象</param>
        /// <param name="lyrname">图层名称</param>
        /// <param name="visible">显示状态</param>
        [Obsolete("已废弃，功能逻辑可能有问题，暂时不要使用")]
        public static void SetLayerVisible(IMap map, string lyrname, bool visible)
        {
            string[] s = lyrname.Split("/".ToCharArray());            
            int j = 0;
            ILayer lyr;
            ICompositeLayer cmpLayer = null;
            for (int i = 1; i < s.Length; i++)
            {
                if (i == 1)
                {
                    lyr = GetLayer(map, s[i - 1], ref j);
                }
                else
                {
                    lyr = GetLayer(cmpLayer, s[i - 1], 0);
                }
                cmpLayer = (ICompositeLayer)lyr;
                if (visible == true)
                {
                    lyr.Visible = true;
                }
            }
            if (s.Length == 1)
            {
                lyr = GetLayer(map, s[s.Length - 1], ref j);
            }
            else
            {
                lyr = GetLayer(cmpLayer, s[s.Length - 1], 0);
            }
            lyr.Visible = visible;
            if (lyr is ICompositeLayer)
            {
                cmpLayer = (ICompositeLayer)lyr;
                SetLayerVisible(cmpLayer, visible);
            }
        }

        /// <summary>
        /// 设置图层组的显示状态，若设为显示状态，则同时设置子图层
        /// </summary>
        /// <param name="compositeLayer">图层组</param>
        /// <param name="visible">显示状态</param>
        [Obsolete("已废弃，功能逻辑可能有问题，暂时不要使用")]
        public static void SetLayerVisible(ICompositeLayer compositeLayer, bool visible)
        {
            if (!visible) //不显示时，若为图层组，则只需设置图层组不显示即可
            {
                (compositeLayer as ILayer).Visible = false;
                return;
            }
            for (int i = 0; i < compositeLayer.Count; i++)
            {
                ILayer lyr = compositeLayer.get_Layer(i);
                lyr.Visible = visible;
                if (lyr is ICompositeLayer)
                    SetLayerVisible((ICompositeLayer)lyr, visible);
            }
        }

        /// <summary>
        /// 通过图层名称在图层组中找到该图层
        /// </summary>
        /// <param name="compLayer">图层组</param>
        /// <param name="lyrName">图层名称</param>
        /// <param name="index">开始索引位置</param>
        /// <returns></returns>
        [Obsolete("已废弃，功能逻辑可能有问题，暂时不要使用")]
        public static ILayer GetLayer(ICompositeLayer compLayer, string lyrName, int index = 0)
        {
            for (int i = index; i < compLayer.Count; i++)
            {
                ILayer lyr = compLayer.get_Layer(i);
                if (lyr.Name.Equals(lyrName, StringComparison.CurrentCultureIgnoreCase))
                {
                    return lyr;
                }
            }
            return null;
        }

        /// <summary>
        /// 通过图层名称在地图上找到该图层，并获取其索引号
        /// </summary>
        /// <param name="map">地图对象</param>
        /// <param name="lyrName">图层名称</param>
        /// <param name="index">开始索引位置</param>
        /// <returns></returns>
        [Obsolete("已废弃，功能逻辑可能有问题，暂时不要使用")]
        public static ILayer GetLayer(IMap map, string lyrName, ref int index)
        {
            for (int i = index; i < map.LayerCount; i++)
            {
                ILayer lyr = map.get_Layer(i);
                if (lyr.Name.Equals(lyrName, StringComparison.CurrentCultureIgnoreCase))
                {
                    index = i;
                    return lyr;
                }
            }
            index = -1;
            return null;
        }
    }
}
